/*
 * Copyright 2013-2018 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.camera.handle.demos.web;

import com.aliyun.facebody20191230.models.FaceBeautyResponse;
import com.aliyun.facebody20191230.models.GenerateHumanAnimeStyleResponse;
import com.aliyun.tea.TeaException;
import com.aliyun.tea.TeaModel;
import com.camera.handle.util.*;
import com.google.common.collect.Maps;
import com.sun.jna.WString;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.blackdread.cameraframework.api.camera.CanonCamera;
import org.blackdread.cameraframework.api.command.CanonCommand;
import org.blackdread.cameraframework.api.command.TerminateSdkCommand;
import org.blackdread.cameraframework.api.constant.EdsISOSpeed;
import org.blackdread.cameraframework.api.constant.EdsSaveTo;
import org.blackdread.cameraframework.api.helper.factory.CanonFactory;
import org.blackdread.cameraframework.api.helper.initialisation.FrameworkInitialisation;
import org.blackdread.cameraframework.api.helper.logic.event.CameraAddedListener;
import org.blackdread.cameraframework.api.helper.logic.event.CameraObjectListener;
import org.blackdread.cameraframework.api.helper.logic.event.CameraPropertyListener;
import org.blackdread.cameraframework.api.helper.logic.event.CameraStateListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import org.blackdread.camerabinding.jna.EdsdkLibrary;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * @author <a href="mailto:chenxilzx1@gmail.com">theonefx</a>
 */
@Controller
public class BasicController {

    private static final Logger log = LoggerFactory.getLogger(BasicController.class);

    private CameraAddedListener cameraAddedListener;

    private CameraObjectListener cameraObjectListener;

    private CameraPropertyListener cameraPropertyListener;

    private CameraStateListener cameraStateListener;

    private static final String LIBRARY_PATH_PROPERTY_KEY = "blackdread.cameraframework.library.path";

    private static final String PRINTER_PORT_NAME_KEY = "PRINTER_PORT_NAME_KEY";

    private static final String DLIBRARY_PATH_KEY = "DLIBRARY_PATH_KEY";

    @Value("${blackdread.cameraframework.library.path:null}")
    private String libraryPathValue;

    @Value("${download.path:null}")
    private String downloadPath;

    @Value("${live.streaming.path:null}")
    private String liveStreamingPath;


    @Value("${printerPortNameDefaultValue:null}")
    private String printerPortNameDefaultValue;

    @Value("${printerDLibraryPathDefaultValue:null}")
    private String printerDLibraryPathDefaultValue;

    private final AtomicBoolean propertyEvent = new AtomicBoolean(false);

    private boolean isStartLiveStreaming = false;

    ExecutorService executorService = Executors.newCachedThreadPool();

    CanonCamera camera = null;

//    private boolean isPausedLiveStreaming = false;

    private boolean isSendStopLiveStreaming = false;

    private boolean isStopLiveStreaming = true;


    // http://127.0.0.1:8080/hello?name=lisi
    @RequestMapping("/hello")
    @ResponseBody
    public String hello(@RequestParam(name = "name", defaultValue = "unknown user") String name) {
        return "Hello " + name;
    }

    // http://127.0.0.1:8080/user
    @RequestMapping("/user")
    @ResponseBody
    public User user() {
        User user = new User();
        user.setName("theonefx");
        user.setAge(666);
        return user;
    }

    // http://127.0.0.1:8080/save_user?name=newName&age=11
    @RequestMapping("/save_user")
    @ResponseBody
    public String saveUser(User u) {
        return "user will save: name=" + u.getName() + ", age=" + u.getAge();
    }



    @RequestMapping("/photo")
    @ResponseBody
    public Map<String,Object> photo(String liveStreamingDownloadRelativePath,String liveStreamingDownloadPath) {
        Map<String, Object> map = Maps.newHashMap();
        map.put("code",0);
        try{

            setPropertyLibraryValue();

            canonCameraInit();

            FileUtils.deleteFile(new File(downloadPath),0,(new Date().getTime() - 24L * 60L * 60L * 1000L));

            isSendStopLiveStreaming = true;

            if(!isStopLiveStreaming){
                for (int i=0; i < 10; i ++){
                    if(isStopLiveStreaming){
                        break;
                    }
                    Thread.sleep(50);
                }
            }


            final String artist = get(camera.getProperty().getArtistAsync());
            log.info("artist: {}", artist);

            final String serial = get(camera.getProperty().getBodyIDExAsync());
            log.info("serial: {}", serial);

            final EdsISOSpeed isoSpeed = get(camera.getProperty().getIsoSpeedAsync());
            log.info("isoSpeed: {}", isoSpeed);

//        camera.getProperty().setSaveToAsync(EdsSaveTo.kEdsSaveTo_Host);

            final EdsSaveTo saveTo = get(camera.getProperty().getSaveToAsync());
            log.info("saveTo: {}", saveTo);


            CanonCamera.Shoot shoot = camera.getShoot();
            List<File> files  = shoot.shoot();
            System.out.println("------------ : " + (null!=files&&files.size()>0?files.size():0));


            List<Map<Object, Object>> fileList = new ArrayList<>();
            if(StringUtils.isNotEmpty(downloadPath)&&!downloadPath.trim().equals("null")){
                String dateFormat = DateFormatUtils.format(new Date(), "yyyy-MM-dd_HH-mm-ss");
                String fileDownloadPath = downloadPath + File.separator + dateFormat;
                FileUtils.fileExist(fileDownloadPath);
                if(!CollectionUtils.isEmpty(files)){
                    for(File file : files){
                        if(null!=file){
                            Map<Object, Object> fileMap = Maps.newHashMap();
                            if(null!=file.getAbsolutePath()){
                                String downloadFilePath = fileDownloadPath + File.separator + file.getName();
                                FileUtils.copyFile(file.getAbsolutePath(),downloadFilePath);
                                fileMap.put("downloadFilePath",downloadFilePath);
                                fileMap.put("fileName",file.getName());
                                fileMap.put("downloadRelativePath", dateFormat + File.separator + file.getName());
                                fileList.add(fileMap);
                            }
                        }
                    }
                }
            }else {
                map.put("msg","下载目录不存在");
            }

            map.put("fileList",fileList);
            map.put("code",1);


            if(StringUtils.isNotEmpty(liveStreamingDownloadRelativePath)&&StringUtils.isNotEmpty(liveStreamingDownloadPath)){
                executorService.execute(new Runnable() {
                    @Override
                    public void run() {
//                        try {
//                            Thread.sleep(50);
//                        } catch (InterruptedException e) {
//                            throw new RuntimeException(e);
//                        }
                        if(!isStartLiveStreaming){
                            startLiveStreamingRun(0,liveStreamingDownloadRelativePath,liveStreamingDownloadPath);
                        }
                    }
                });
            }

//            get(camera.closeSession());

//            CanonFactory.commandDispatcher().scheduleCommand(new TerminateSdkCommand());

        }catch (Exception e){
            e.printStackTrace();
            try{
                closeCamera();
                Thread.sleep(100);
                canonCameraInit();
            }catch (Exception e1){
                e1.printStackTrace();
            }
        }
        return map;
    }




    @RequestMapping("/liveStreaming")
    @ResponseBody
    public Map<String,Object> liveStreaming() {
        Map<String, Object> map = Maps.newHashMap();
        map.put("code",0);
        try{
            String dateFormat = DateFormatUtils.format(new Date(), "yyyy-MM-dd_HH-mm-ss");
            String uuid = UUID.randomUUID().toString();
            String liveStreamingDownloadRelativePath = dateFormat + File.separator + uuid;
            String liveStreamingDownloadPath = liveStreamingPath + File.separator + liveStreamingDownloadRelativePath;
            if(!isStartLiveStreaming){
                if(StringUtils.isNotEmpty(liveStreamingPath)&&!liveStreamingPath.trim().equals("null")){
                    startLiveStreamingRun(0,liveStreamingDownloadRelativePath,liveStreamingDownloadPath);
                    map.put("liveStreamingDownloadRelativePath",liveStreamingDownloadRelativePath);
                    map.put("liveStreamingDownloadPath",liveStreamingDownloadPath);
                    map.put("code",1);
                }else {
                    map.put("msg","下载目录不存在");
                }
            }else{
                map.put("msg","正在获取实时流中");
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return map;
    }


    @RequestMapping("/stopStreaming")
    @ResponseBody
    public Map<String,Object> stopStreaming() {
        Map<String, Object> map = Maps.newHashMap();
        map.put("code",0);
        try{
            if(isStopLiveStreaming){
                map.put("msg","实时流未开启");
            }else {
                isStopLiveStreaming = true;
                executorService.execute(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            Thread.sleep(500);
                        } catch (InterruptedException e) {
                            throw new RuntimeException(e);
                        }
                        if(!isStartLiveStreaming){
                            FileUtils.deleteFile(new File(liveStreamingPath),0);
                            FileUtils.fileExist(liveStreamingPath);
                        }
                    }
                });
            }
            map.put("msg","实时流停止中");
            map.put("code",1);
        }catch (Exception e){
            e.printStackTrace();
        }
        return map;
    }



    private void startLiveStreamingRun(int runCount,String liveStreamingDownloadRelativePath,String liveStreamingDownloadPath){
        try{
            if(!isStartLiveStreaming){
                if(runCount<=10){
                    executorService.execute(new Runnable() {
                        @Override
                        public void run() {
                            startLiveStreaming(runCount,liveStreamingDownloadRelativePath,liveStreamingDownloadPath);
                        }
                    });
                }else{
                    System.out.println(DateFormatUtils.format(new Date(), "yyyy-MM-dd HH-mm-ss") + " : runCount 超过限制次数, runCount : " + runCount + " liveStreamingDownloadPath : " + liveStreamingDownloadPath);
                }
            }else{
                System.out.println(DateFormatUtils.format(new Date(), "yyyy-MM-dd HH-mm-ss") + " : isStartLiveStreaming 运行中, liveStreamingDownloadPath : " + liveStreamingDownloadPath);
            }
        }catch (Exception e){
            e.printStackTrace();
        }

    }

    private void startLiveStreaming(int runCount,String liveStreamingDownloadRelativePath,String liveStreamingDownloadPath){
        int isRestRun = 0;
        try{
            synchronized (LIBRARY_PATH_PROPERTY_KEY){
                setPropertyLibraryValue();

                isStartLiveStreaming = true;

                canonCameraInit();

                Long startTime = new Date().getTime();

                isStopLiveStreaming = false;
                propertyEvent.set(false);
                get(camera.getLiveView().beginLiveViewAsync());

                while (!propertyEvent.get()) {
                    Thread.sleep(100);
                    if(new Date().getTime()-startTime > 3L*1000L){
                        throw new RuntimeException();
                    }
                }

                while (!get(camera.getLiveView().isLiveViewActiveAsync())) {
                    Thread.sleep(500);
                    if(new Date().getTime()-startTime > 3L*1000L){
                        throw new RuntimeException();
                    }
                }

                // if try to download too quick live view then will get "EDS_ERR_OBJECT_NOTREADY"
                Thread.sleep(200);

                FileUtils.fileExist(liveStreamingDownloadPath);
                int i = 0;
                for (;;) {
                    if(isSendStopLiveStreaming){
                        break;
                    }
                    if(isStopLiveStreaming){
                        break;
                    }
                    final BufferedImage bufferedImage = get(camera.getLiveView().downloadLiveViewAsync());
                    // if try to download too quick live view then will get "EDS_ERR_OBJECT_NOTREADY"
                    Thread.sleep(30);

                    final int tempI = i;
                    CompletableFuture.runAsync(() -> {
                        try {
                            ImageIO.write(bufferedImage, "jpeg", new File(liveStreamingDownloadPath + File.separator +  "image-" + tempI + ".jpg"));
                        } catch (IOException e) {
                            throw new IllegalStateException(e);
                        }
                    });
                    i = i + 1;
                }

            }
        }catch (Exception e){
            e.printStackTrace();
            try{
                get(camera.getLiveView().endLiveViewAsync());
            }catch (Exception e1){
                e1.printStackTrace();
            }
            closeCamera();
            isRestRun = 1;
            try{
                Thread.sleep(100);
            }catch (Exception e1){
                e1.printStackTrace();
            }
        }finally {
            if(null!=camera){
                get(camera.getLiveView().endLiveViewAsync());
            }
            isStartLiveStreaming = false;
            isSendStopLiveStreaming = false;

            if(!isStopLiveStreaming){
                isStopLiveStreaming = true;
                if(isRestRun == 1){
                    startLiveStreamingRun(runCount + 1,liveStreamingDownloadRelativePath,liveStreamingDownloadPath);
                }
            }
        }
    }

    private CanonCamera canonCameraInit(){
        if(null==camera){
            CameraAddedListener cameraAddedListener = event -> {
                log.info("Camera added detected: {}", event);
            };
            CameraObjectListener cameraObjectListener = event -> {
                log.info("Object event: {}", event);
            };
            CameraPropertyListener cameraPropertyListener = event -> {
                log.info("Property event: {}", event);
                propertyEvent.set(true);
            };
            CameraStateListener cameraStateListener = event -> {
                log.info("State event: {}", event);
            };
            new FrameworkInitialisation()
                    .registerCameraAddedEvent()
                    .withEventFetcherLogic()
                    .withCameraAddedListener(cameraAddedListener)
                    .initialize();

            camera = new CanonCamera();

            final EdsdkLibrary.EdsCameraRef edsCameraRef = get(camera.openSession());
//        camera.setCameraRef(edsCameraRef); // not necessary as by default on success the ref is set by the openSession command

            get(camera.getEvent().registerObjectEventCommand());
            get(camera.getEvent().registerPropertyEventCommand());
            get(camera.getEvent().registerStateEventCommand());

            CanonFactory.cameraObjectEventLogic().addCameraObjectListener(cameraObjectListener);
            CanonFactory.cameraPropertyEventLogic().addCameraPropertyListener(edsCameraRef, cameraPropertyListener);
            CanonFactory.cameraStateEventLogic().addCameraStateListener(edsCameraRef, cameraStateListener);
        }
        return camera;
    }

    private void closeCamera(){
       try{
           if(null!=camera){
               get(camera.closeSession());
               CanonFactory.commandDispatcher().scheduleCommand(new TerminateSdkCommand());
               camera = null;
           }
//           return camera;
       }catch (Exception e){
           e.printStackTrace();
       }
    }


    @GetMapping("/downloadImage")
    public void downloadImage(HttpServletResponse resp,String downloadRelativePath) throws IOException {
        final InputStream in = getImgInputStream(downloadPath + File.separator + downloadRelativePath);
        resp.setContentType(MediaType.IMAGE_PNG_VALUE);
        IOUtils.copy(in, resp.getOutputStream());
    }


    @GetMapping("/liveStreamingLastImag")
    public void liveStreamingLastImag(HttpServletResponse resp,String liveStreamingDownloadRelativePath) throws IOException {
        liveStreamingLastImage(resp,liveStreamingDownloadRelativePath);
    }

    @GetMapping("/liveStreamingLastImage")
    public void liveStreamingLastImage(HttpServletResponse resp,String liveStreamingDownloadRelativePath) throws IOException {
        File lastFile = getLastFile(liveStreamingDownloadRelativePath);
        final InputStream in = getImgInputStream(lastFile.getPath());
        resp.setContentType(MediaType.IMAGE_PNG_VALUE);
        IOUtils.copy(in, resp.getOutputStream());
    }


    @GetMapping("/liveStreamingLastBase64Image")
    @ResponseBody
    public Map<String,Object> liveStreamingLastBase64Image(HttpServletResponse resp,String liveStreamingDownloadRelativePath) throws IOException {
        Map<String,Object> map = Maps.newHashMap();
        map.put("code",0);
        try{
            File lastFile = getLastFile(liveStreamingDownloadRelativePath);
            if(null!=lastFile){
                final byte[] bytes = IOUtils.toByteArray(getImgInputStream(lastFile.getPath()));
                map.put("imgBase64",Base64.getEncoder().encodeToString(bytes));
                map.put("code",1);
            }else{
                map.put("msg","实时流抓取中");
            }
        }catch (Exception e){
            e.printStackTrace();
            map.put("msg",e.getMessage());
        }
        return map;
    }

    private File getLastFile(String liveStreamingDownloadRelativePath){
        if(StringUtils.isNotEmpty(liveStreamingDownloadRelativePath)){
            File directory=new File(liveStreamingPath + File.separator + liveStreamingDownloadRelativePath);
            File[] listFiles = directory.listFiles();
            File lastFile = null;
            if(null!=listFiles&&listFiles.length>0){
                for(int i=0;i<listFiles.length;i++){
                    if(null!=listFiles[i]){
                        if(null==lastFile||lastFile.lastModified()<listFiles[i].lastModified()){
                            lastFile = listFiles[i];
                        }
                    }
                }
            }
            return lastFile;
        }
        return null;
    }


    private InputStream getImgInputStream(String imagePath) throws FileNotFoundException {
        return new FileInputStream(new File(imagePath));
    }




    @RequestMapping("/beauty")
    @ResponseBody
    public Map<String,Object> beauty(String imageUrl,Float white,Float smooth,Float sharp) {
        Map<String, Object> map = Maps.newHashMap();
        map.put("code",0);
        try{
            white = null!=white?white:0.3F;
            sharp = null!=sharp?sharp:0.0F;
            smooth = null!=smooth?smooth:0.0F;
            if(!StringUtils.isNotEmpty(imageUrl)){
                map.put("msg","请传递imageUrl");
                return map;
            }
            com.aliyun.facebody20191230.Client client = FacebodyUtils.createClient();
            com.aliyun.facebody20191230.models.FaceBeautyRequest faceBeautyRequest = new com.aliyun.facebody20191230.models.FaceBeautyRequest()
                    .setImageURL(imageUrl)
                    .setSharp(sharp)
                    .setSmooth(smooth)
                    .setWhite(white);
            com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
            try {
                // 复制代码运行请自行打印 API 的返回值
                FaceBeautyResponse faceBeautyResponse = client.faceBeautyWithOptions(faceBeautyRequest, runtime);
                System.out.println(faceBeautyResponse);
                if(null!=faceBeautyResponse&&null!=faceBeautyResponse.getStatusCode()&&faceBeautyResponse.getStatusCode().intValue() == 200){
                    System.out.println(faceBeautyResponse.getBody());
                    if(null!=faceBeautyResponse.getBody()&&null!=faceBeautyResponse.getBody().getData()&&StringUtils.isNotEmpty(faceBeautyResponse.getBody().getData().getImageURL())){
                        System.out.println(faceBeautyResponse.getBody().getData().getImageURL());
                        String beautyTempImageUrl = faceBeautyResponse.getBody().getData().getImageURL();
                        map.put("beautyTempImageUrl",beautyTempImageUrl);
                        String beautyOssImageUrl = OssUtils.uploadOssUrl(beautyTempImageUrl);
                        if(StringUtils.isNotEmpty(beautyOssImageUrl)){
                            map.put("beautyOssImageUrl",beautyOssImageUrl);
                            map.put("code",1);
                        }
                    }
                }
            } catch (TeaException error) {
                // 此处仅做打印展示，请谨慎对待异常处理，在工程项目中切勿直接忽略异常。
                // 错误 message
                System.out.println(error.getMessage());
                map.put("msg",error.getMessage());
                // 诊断地址
                System.out.println(error.getData().get("Recommend"));
                com.aliyun.teautil.Common.assertAsString(error.message);
            } catch (Exception _error) {
                TeaException error = new TeaException(_error.getMessage(), _error);
                // 此处仅做打印展示，请谨慎对待异常处理，在工程项目中切勿直接忽略异常。
                // 错误 message
                System.out.println(error.getMessage());
                map.put("msg",error.getMessage());
                // 诊断地址
                System.out.println(error.getData().get("Recommend"));
                com.aliyun.teautil.Common.assertAsString(error.message);
            }
        }catch (Exception e){
            e.printStackTrace();
            map.put("msg",e.getMessage());
        }
        return map;
    }


    @RequestMapping("/comicStyle")
    @ResponseBody
    public Map<String,Object> comicStyle(String imageUrl,String algoType) {
        Map<String, Object> map = Maps.newHashMap();
        map.put("code",0);
        try{
            algoType = StringUtils.isNotEmpty(algoType)?algoType:"hongkong";
            String accessKeyId = ConstantUtils.aliyunAccessKeyId;
            String accessKeySecret = ConstantUtils.aliyunAccessKeySecret;
            com.aliyun.facebody20191230.Client client = GenerateHumanAnimeStyle.createClient(accessKeyId, accessKeySecret);
            com.aliyun.facebody20191230.models.GenerateHumanAnimeStyleRequest generateHumanAnimeStyleRequest = new com.aliyun.facebody20191230.models.GenerateHumanAnimeStyleRequest()
                    .setImageURL(imageUrl)
                    .setAlgoType(algoType);
            com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
            try {
                // 复制代码运行请自行打印 API 的返回值
                GenerateHumanAnimeStyleResponse response = client.generateHumanAnimeStyleWithOptions(generateHumanAnimeStyleRequest, runtime);
                // 获取整体结果
                System.out.println(com.aliyun.teautil.Common.toJSONString(TeaModel.buildMap(response)));
                if(null!=response&&null!=response.getStatusCode()&&response.getStatusCode().intValue() == 200){
//                    System.out.println(response.getBody());
                    if(null!=response.getBody()&&null!=response.getBody().getData()&&StringUtils.isNotEmpty(response.getBody().getData().getImageURL())){
                        System.out.println(response.getBody().getData().getImageURL());
                        String comicStyleTempImageUrl = response.getBody().getData().getImageURL();
                        map.put("comicStyleTempImageUrl",comicStyleTempImageUrl);
                        String comicStyleOssImageUrl = OssUtils.uploadOssUrl(comicStyleTempImageUrl);
                        if(StringUtils.isNotEmpty(comicStyleOssImageUrl)){
                            map.put("comicStyleOssImageUrl",comicStyleOssImageUrl);
                            map.put("code",1);
                        }
                        map.put("code",1);
                    }
                }
            } catch (TeaException error) {
                // 获取整体报错信息
                System.out.println(com.aliyun.teautil.Common.toJSONString(error));
                map.put("msg",com.aliyun.teautil.Common.toJSONString(error));
                // 获取单个字段
                System.out.println(error.getCode());
            }
        }catch (Exception e){
            map.put("msg",e.getMessage());
            e.printStackTrace();
        }
        return map;
    }



    @RequestMapping("/printerModeSet")
    @ResponseBody
    public Map<String,Object> printerModeSet(Integer modeType) {
        Map<String, Object> map = Maps.newHashMap();
        map.put("code",0);
        try{
            modeType = null!=modeType?modeType:DnpPrinterUtils.CUTTER_MODE_2INCHCUT;
            setPropertyPrinterDLibraryPathValue();
            Long usbPort = -1L;
            String propertyPrinterPortNameValue = getPropertyPrinterPortNameValue();
            if(StringUtils.isNotEmpty(propertyPrinterPortNameValue)&&!DnpPrinterUtils.portNameList.contains(propertyPrinterPortNameValue.trim())){
                DnpPrinterUtils.portNameList.add(0,propertyPrinterPortNameValue);
            }
            for(String portName : DnpPrinterUtils.portNameList){
                if(StringUtils.isNotEmpty(portName)){
                    Long usbNamePort = DnpPrinterUtils.DLibrary.INSTANCE.PortInitialize(new WString(portName));
                    if(usbNamePort!=-1&&usbNamePort!=4294967295L&&usbNamePort<700000){
                        usbPort = usbNamePort;
                        break;
                    }
                }
            }
            if(usbPort>0L){
//                System.out.println("usbPort : " + usbPort);
                Boolean isSetMode =  DnpPrinterUtils.DLibrary.INSTANCE.SetCutterMode(usbPort, modeType);
                System.out.println("SetCutterMode : " + isSetMode);
                if(isSetMode){
                    map.put("code",1);
                }
            }
        }catch (Exception e){
            e.printStackTrace();
            try{
                closeCamera();
                Thread.sleep(100);
                canonCameraInit();
            }catch (Exception e1){
                e1.printStackTrace();
            }
        }
        return map;
    }



    @ModelAttribute
    public void parseUser(@RequestParam(name = "name", defaultValue = "unknown user") String name
            , @RequestParam(name = "age", defaultValue = "12") Integer age, User user) {
        user.setName("zhangsan");
        user.setAge(18);
    }

    private void setPropertyLibraryValue(){
        if(StringUtils.isEmpty(System.getProperty(LIBRARY_PATH_PROPERTY_KEY))){
            String envValue = System.getenv(LIBRARY_PATH_PROPERTY_KEY);
            if(StringUtils.isNotEmpty(envValue)){
                System.setProperty(LIBRARY_PATH_PROPERTY_KEY,envValue);
            }
            if(StringUtils.isEmpty(System.getProperty(LIBRARY_PATH_PROPERTY_KEY))){
                if(StringUtils.isNotEmpty(libraryPathValue)&&!libraryPathValue.trim().equals("null")){
                    System.setProperty(LIBRARY_PATH_PROPERTY_KEY,libraryPathValue);
                }
            }
            if(StringUtils.isEmpty(System.getProperty(LIBRARY_PATH_PROPERTY_KEY))){
                System.setProperty(LIBRARY_PATH_PROPERTY_KEY,"\\EDSDK_64\\Dll\\EDSDK.dll");
            }

        }
    }


    private String getPropertyPrinterPortNameValue(){
        String envValue = System.getenv(PRINTER_PORT_NAME_KEY);
        if(StringUtils.isNotEmpty(envValue)){
            return envValue;
        }

        if(StringUtils.isNotEmpty(printerPortNameDefaultValue)&&!printerPortNameDefaultValue.trim().equals("null")){
            return printerPortNameDefaultValue;
        }
        return null;
    }

    private String setPropertyPrinterDLibraryPathValue(){
        String filePath = DnpPrinterUtils.DLibrary.class.getResource("").getPath().replaceFirst("/","").replaceAll("%20"," ")+"Cx2Stat64.dll";
        System.out.println("setPropertyPrinterDLibraryPathValue : filePath " + filePath);
        String envValue = System.getenv(DLIBRARY_PATH_KEY);
        if(StringUtils.isNotEmpty(envValue)){
            DnpPrinterUtils.DLIBRARY_PATH = envValue;
            System.out.println("setPropertyPrinterDLibraryPathValue : DLIBRARY_PATH envValue " + envValue);
            return envValue;
        }

        if(StringUtils.isNotEmpty(printerDLibraryPathDefaultValue)&&!printerDLibraryPathDefaultValue.trim().equals("null")){
            DnpPrinterUtils.DLIBRARY_PATH = printerDLibraryPathDefaultValue;
            System.out.println("setPropertyPrinterDLibraryPathValue : DLIBRARY_PATH " + printerDLibraryPathDefaultValue);
            return printerDLibraryPathDefaultValue;
        }
        return null;
    }

    private static <R> R get(final CanonCommand<R> command) {
        try {
            return command.get();
        } catch (InterruptedException | ExecutionException e) {
            throw new IllegalStateException(e);
        }
    }
}
